#include "../bulk_storage/bulk_storage.h"
#include "atom.h"
#include "../m_tree/mTree.h"
#include "residue.h"

#include <string.h>
#include <assert.h>
#include <argp.h>

#define EXIT_FAILURE 1
//#define PACKAGE "read_residue"   // This doesn't go here... it's in config.h
//#define VERSION "0.98"

#if ENABLE_NLS
# include <libintl.h>
# define _(Text) gettext (Text)
#else
# define textdomain(Domain)
# define _(Text) Text
#endif
#define N_(Text) Text

static error_t parse_opt (int key, char *arg, struct argp_state *state);
static void show_version (FILE *stream, struct argp_state *state);
double local_res_med(const struct residue* r0, const struct residue* r1);
/* argp option keys */
enum {DUMMY_KEY=129
};

/* Option flags and variables.  These are initialized in parse_opt.  */
char* rName;			/* --output=FILE */
struct store* rStore=0;
char* aName;
struct store* aStore=0;
/*  struct mTree* medTree=0; */

static struct argp_option options[] =
{
  { "output",      'o',           N_("FILE"),      0,
    N_("Send output to FILE instead of standard output"), 0 },
  { NULL, 0, NULL, 0, NULL, 0 }
};

/* The argp functions examine these global variables.  */
const char *argp_program_bug_address = "<gibbss@genome.osu.edu>";
void (*argp_program_version_hook) (FILE *, struct argp_state *) = show_version;

static struct argp argp =
{
  options, parse_opt, N_("[FILE...]"),
  N_("scratch"),
  NULL, NULL, NULL
};

int main (int argc, char** argv) {
  int ares;
  off_t o=1, u=0;
  struct atom* a;
  struct residue* r;

  textdomain(PACKAGE);
  argp_parse(&argp, argc, argv, 0, NULL, NULL);

  assert(aStore != 0);
  if(rStore == 0){
    rStore = store_open_cached("0000.residue", "0000.residue.fat", 
			       sizeof(struct residue), 32, 100);
  }
/*    if(medTree == 0){ */
/*      medTree = mTree_open_cached(rStore, "0000.residue.mTree",  */
/*  				"0000.residue.mTree.fat", */
/*    				100, (double(*)(const void*, const void*))&local_res_med);  */
/*    } */


  ares = -1;
  /* Dummy up residue 0 */
  u = store_new(rStore);
  r = (struct residue*)store_read(rStore, u);
  r->startA = 0;

  a = (struct atom*)(store_read(aStore, o));

  while(a->name[0] != '\0'){
    if(a->residue != ares){

      /* Finish off a residue. Only write real
       * residues to the bulk store. 
       */
      if(r->residue_type != '\0'){
	r->stopA = o-1;
/*        printf("%Ld\n", r->stopA);  */
	store_write(rStore, u);
/*  	mTree_insert(medTree, u); */
      }
      store_release(rStore, u);

      /* Start a new residue  */
      u = store_new(rStore);
      r = (struct residue*)store_read(rStore, u);
      r->startA = o;
      r->residue_type = a->residue_type;
      ares = a->residue;
/*          printf("%c: %Ld - ", r->residue_type, r->startA);  */
    }
    
    /*      if(strncmp(" CA ", a->name) == 0){ */
    /*        r->CA = o; */
    /*      } */
    
    store_release(aStore, o);
    o++;
    a = (struct atom*)(store_read(aStore, o));
  }
  /* Flush last struct   */
  r->stopA = o-1;
  store_write(rStore, u);
/*    mTree_insert(medTree, u); */
  store_release(rStore, u);  
  store_release(aStore, o);
  
  /* Write an EOF struct.  */
  u = store_new(rStore);
  r = (struct residue*)store_read(rStore, u);
  r->startA=0;
  store_write(rStore, u);
  store_release(rStore, u);  


  store_close(aStore);
  store_close(rStore);
  return 0;
}

double local_res_med(const struct residue* r0, const struct residue* r1){
  return(residue_min_effect_dist(r0, r1, aStore));
}


/** Parse a single command line option.  */
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
  char* tmp0;
/*    char* tmp1; */
  switch (key)
    {
    case ARGP_KEY_INIT:
      /* Set up default values.  */
      rName = "0000.residue";
      break;

    case 'o':			/* --output */
      rName = strdup (arg);
      tmp0 = strdup(rName);
      rStore = store_open_cached(rName, strcat(tmp0, ".fat"), 
				 sizeof(struct residue), 32, 100);
/*        tmp0 = strdup(rName); */
/*        strcat(tmp0, ".mTree"); */
/*        tmp1 = strdup(tmp0); */
/*        medTree = mTree_open_cached(rStore, tmp0, strcat(tmp1, ".fat"), */
/*  				  100, (double(*)(const void*, const void*))&local_res_med); */
      if (!rStore)
	argp_failure (state, EXIT_FAILURE, errno,
		      _("Cannot open '%s' for output"), rName);
      break;

    case ARGP_KEY_ARG:		/* [FILE]... */
      aName = strtok(arg, " \t");
      tmp0 = strdup(aName);
      aStore = store_open_cached(aName, strcat(tmp0, ".fat"),
				 sizeof(struct atom), 32, 100);
			     
      if (!aStore)
	argp_failure (state, EXIT_FAILURE, errno,
		      _("Cannot open '%s' for input"), aName);
      break;

    default:
      return ARGP_ERR_UNKNOWN;
    }
  return 0;
}

static void show_version (FILE *stream, struct argp_state *state) {
  fprintf(stream, "no version right now....");
}

/** Show the version number and copyright information.  */
//static void
//show_version (FILE *stream, struct argp_state *state)
//{
//  (void) state;
  /* Print in small parts whose localizations can hopefully be copied
     from other programs.  */
//  fputs(PACKAGE" "VERSION"\n", stream);
//  fprintf(stream, _("Written by %s.\n\n"), "Solomon Gibbs");
//  fprintf(stream, _("Copyright (C) %s %s\n"), "2003", "Solomon Gibbs");
//  fputs(_("

/*This program is free software; you may redistribute it under the terms of\n\
//the GNU General Public License.  This program has absolutely no warranty.\n"),
//	stream);
//}

*/
 
